//==============================================================================
//
//            DLong - the long number class in the ofc-library
//
//               Copyright (C) 2003  Dick van Oudheusden
//  
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public
// License along with this library; if not, write to the Free
// Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
//==============================================================================
// 
//  $Date: 2004-02-20 20:16:35 $ $Revision: 1.10 $
//
//==============================================================================

#include "ofc/DLong.h"

#include <limits.h>
#include <stdlib.h>


#if _INTERFACE_

#include "ofc/config.h"

#include "ofc/DComparable.h"
#include "ofc/DTextable.h"
#include "ofc/DDatable.h"
#include "ofc/DParsable.h"

#include "ofc/DText.h"
#include "ofc/DData.h"

// The long class implements a number of methods for storing and manipulating long numbers.

@interface DLong : Object <DComparable,DTextable,DDatable,DParsable>
{
@private
  long        _nr;
}

#endif



@implementation DLong


//// Constructors

//
// Initialises to zero number
//
// @return the object
//

- (DLong *) init
{
  [super init];

  _nr = 0;
  
  return self;
}

//
// Initialise to a number
//
// @param number   the number
//
// @return the object
//

- (DLong *) init :(long) number
{
  [self init];

  _nr = number;

  return self;
}


//// Member methods

//
// Get the long number
//
// @return the number
//

- (long) get
{
  return _nr;
}

//
// Set the long number
//
// @param number  the long
//
// @return the object
//

- (DLong *) set :(long) number
{
  _nr = number;

  return self;
}



//// Comparable protocol


//
// Compare two long objects
//
// @param other    the object to compare with
//
// @return the result of the comparison (-1,0,1)
//

- (long) compare :(DLong *) other
{
  if (self != other)
  {
    long i = [other get];
    
    if (_nr == i)
    {
      return 0;
    }
    else if (_nr > i)
    {
      return 1;
    }
    else
    {
      return -1;
    }
  }
  else
  {
    return 0;
  }
}


//// Parsable protocol

//
// Parse a string for setting the object
//
// @param cstr     the string to be parsed (moved to first non-parsable char)
//
// @return the result (0, ERANGE, ENODATA)
//

- (int) fromString :(char **) cstr
{
  int  result = 0;
  long number = 0L;
  char *src   = *cstr;

  number = strtol(*cstr, cstr, 0);

  if (src == *cstr)
  {
    result = ENODATA;
  }
  if (((number == LONG_MIN) || (number == LONG_MAX)) && (errno == ERANGE))
  {
    result = ERANGE;
  }
  else
  {
    _nr = number;
  }

  return result;
}


//// Textable protocol

//
// Return a text string 
//
// @return a (new) text string with the number
//

- (DText *) toText
{
  return [[[DText alloc] init] format :"%ld",_nr];
}
    

//// Datable protocol

//
// Return a data string
//
// @return a (new) data string
//

- (DData *) toData
{
  return [[DData alloc] init :(unsigned char *)&_nr :sizeof(_nr)];
}


//// Endian methods

//
// Return the BigEndian (network order) order for the object
//
// @return the big endian converted long
//

- (long) toBigEndian
{
  long number = _nr;
  
#ifndef WORDS_BIGENDIAN
  number = ((number >> 24) & 0x000000ff) |
           ((number >> 8)  & 0x0000ff00) | 
           ((number << 8)  & 0x00ff0000) |
           ((number << 24) & 0xff000000);
#endif

  return number;
}

//
// Return the LittleEndian order for the object
//
// @return the little endian converted long
//

- (long) toLittleEndian
{
  long number = _nr;
  
#ifdef WORDS_BIGENDIAN
  number = ((number >> 24) & 0x000000ff) |
           ((number >> 8)  & 0x0000ff00) | 
           ((number << 8)  & 0x00ff0000) |
           ((number << 24) & 0xff000000);
#endif

  return number;
}

@end

/*==========================================================================*/
           
